package com.sanq.product.books.splide;

import com.sanq.product.books.config.Redis;
import com.sanq.product.books.entity.vo.BooksVo;
import com.sanq.product.books.module.ServiceModule;
import com.sanq.product.books.redis.JedisPoolService;
import com.sanq.product.books.worker.Id;
import com.sanq.product.config.utils.date.LocalDateUtils;
import com.sanq.product.config.utils.string.MatcherUtil;
import com.sanq.product.config.utils.string.StringUtil;
import com.sanq.product.config.utils.web.JsonUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * com.sanq.product.books.splide.SplideBooksService
 * <p>
 * 爬取小说列表
 *
 * @author sanq.Yan
 * @date 2019/12/17
 */
@Component
public class SplideBooksService {

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @Resource
    private JedisPoolService jedisPoolService;
    @Resource
    private SplideChapterService splideChapterService;

    @Value("${WORKER_ID}")
    private Integer workerId;
    @Value("${DATACENTER_ID}")
    private Integer datacenterId;


    public static class ReplaceTmp {
        public static final String AUTHOR_TMP_SPACE = "作 者：";
        public static final String AUTHOR_TMP = "作者：";
    }

    public void saveBooks(ServiceModule serviceModule, String sortName , String href) throws IOException {

        //验证URL是否完整， 否则拼接URL
        if (!MatcherUtil.isUrl(href))
            href = serviceModule.getUrl().concat(href);

        Document booksDetail = Jsoup.connect(href).userAgent(serviceModule.getUserAgent()).get();

        Long booksId = Id.getInstance(workerId, datacenterId).getId();

        String booksName = booksDetail.select(serviceModule.getName()).get(0).text();
        String booksCover = booksDetail.select(serviceModule.getCover()).get(0).attr("src");

        if (!MatcherUtil.isUrl(booksCover))
            booksCover = serviceModule.getUrl().concat(booksCover);

        String booksAuthor = booksDetail.select(serviceModule.getAuthor()).get(0).text();
        if (booksAuthor.contains(ReplaceTmp.AUTHOR_TMP_SPACE) ||
                booksAuthor.contains(ReplaceTmp.AUTHOR_TMP)) {
            booksAuthor = booksAuthor.replace(ReplaceTmp.AUTHOR_TMP_SPACE, "").replace(ReplaceTmp.AUTHOR_TMP, "");
        }

        String booksDesc = booksDetail.select(serviceModule.getDescription()).text();

        //如果这本书不存在， 存储
        String existsBooksMsg = String.format("%s:%s", booksName, booksAuthor);
        if (!jedisPoolService.zrank(Redis.RedisKey.EXISTS_BOOKS, existsBooksMsg)) {
            BooksVo booksVo = new BooksVo();
            booksVo.setId(booksId);
            booksVo.setBooksName(booksName);
            booksVo.setBooksCover(booksCover);
            booksVo.setBooksDescription(booksDesc);
            booksVo.setCreateTime(LocalDateUtils.nowTime());
            booksVo.setIsOver("3.11.2");    //连载中
            booksVo.setAuthor(booksAuthor);
            booksVo.setTmpSortName(sortName);
            jedisPoolService.putList(Redis.RedisKey.SPLIDE_BOOKS_LIST_KEY, JsonUtil.obj2Json(booksVo));
            jedisPoolService.putSet(Redis.RedisKey.EXISTS_BOOKS, booksId, existsBooksMsg);
        } else {
            //得到指定内容的分数值， 即booksId
            booksId = StringUtil.toLong(jedisPoolService.getScope(Redis.RedisKey.EXISTS_BOOKS, existsBooksMsg));
        }

        final Long tmp = booksId;
        booksDetail.select(serviceModule.getChapter()).forEach(element -> {
            // TODO 如果使用多线程来爬取小说内容， 在这里章节顺序会混乱。 WTF
            try {
                splideChapterService.saveChapter(serviceModule, tmp, element.text(), serviceModule.getUrl().concat(element.attr("href")));
            } catch (IOException e) {
                e.printStackTrace();
                jedisPoolService.putList("errors", String.format("%s,%s", element.text(), element.attr("href")));
            }

//            taskExecutor.execute(() -> {
//
//            });
        });


    }
}
